// -----------------------------
// Author: 		Dhaenens Gert 
// Creation: 	11/6/2014 8:28:34 PM				
// -----------------------------

#ifndef _SoundSample_h
#define _SoundSample_h

#include "Common.h"

// Sound Sample Structure
struct SoundSample
{
	UInt32			Channels;
	UInt32			SampleRate;
	UInt32			Count;
	Float*			Samples;

	SoundSample()
		: Channels(0)
		, SampleRate(0)
		, Count(0)
		, Samples(nullptr)
	{
	}
	SoundSample(const SoundSample& refSample)
		: Channels(refSample.Channels)
		, SampleRate(refSample.SampleRate)
		, Count(refSample.Count)
		, Samples(nullptr)
	{
		if (refSample.Samples)
		{
			Samples = new Float[Count];
			memcpy_s(Samples, Count * sizeof(Float), refSample.Samples, refSample.Count * sizeof(Float));
		}
	}
	SoundSample& operator=(const SoundSample& refSample)
	{
		if (Samples)
			delete[] Samples;

		Channels = refSample.Channels;
		SampleRate = refSample.SampleRate;
		Count = refSample.Count;

		if (refSample.Samples)
		{
			Samples = new Float[Count];
			memcpy_s(Samples, Count * sizeof(Float), refSample.Samples, refSample.Count * sizeof(Float));
		}

		return (*this);
	}
	~SoundSample()
	{
		delete[] Samples;
	}

	// Get the Duration in Seconds
	// of the Sound Sample
	Float	Duration() const
	{
		return ((Float)Count / SampleRate / Channels);
	}

	// Append 2 Samples
	SoundSample& Append(const SoundSample& sample)
	{
		return (*this).Merge(sample, Count);
	}

	// Merge the 2 Samples
	SoundSample& Merge(const SoundSample& sample, UInt32 sampleOffset = 0)
	{
		Float* lpSamples = Samples;
		UInt32 sampleCount = Count;

		Count = (sampleCount > (sample.Count + sampleOffset)) ? sampleCount : (sample.Count + sampleOffset);
		Samples = new Float[Count];
		memset(Samples, 0, Count * sizeof(Float));

		// Copy the Samples
		for (UInt32 i = 0; i < sampleCount; ++i)
			Samples[i] += lpSamples[i];
		for (UInt32 i = 0; i < sample.Count; ++i)
			Samples[sampleOffset + i] += sample.Samples[i];

		delete[] lpSamples;

		return (*this);
	}

	// Cents to Frequency
	static Float CentsToFreqScale(Int32 cents)
	{
		return Math::Pow(2.0f, (cents / 1200.0f));
	}
};

#endif